home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac: Not for Sale / Another.not.for.sale (Australia).iso / Dr. Doyle / C Lesson / C-LESSON.3 < prev    next >
Text File  |  1993-11-01  |  24KB  |  631 lines

  1.  
  2.                                   Lesson 2
  3.  
  4.                                         Data Storage Concepts.
  5.  
  6.         It has been stated that "data + algorithms = programs".
  7.         This Lesson deals with with the first part of the addition sum.
  8.  
  9.   All information in a computer is stored as numbers represented using the
  10. binary number system. The information may be either program instructions or
  11. data elements. The latter are further subdivided into several different types,
  12. and stored in the computer's memory in different places as directed by the
  13. storage class used when the datum element is defined.
  14.  
  15. These types are:
  16.  
  17.   a) The Character.
  18.  
  19.      This is a group of 8 data bits and in 'C' represents either
  20.      a letter of the Roman alphabet, or a small integer in the range of 0
  21.      through to +255. So to arrange for the compiler to give you a named
  22.      memory area in which to place a single letter you would "say":
  23.  
  24.   char letter;
  25.  
  26.      at the beginning of a program block. You should be aware that
  27.                  whether or not a char is signed or unsigned is dependant
  28.                  on the design of the processor underlying your compiler.
  29.                  In particular, note that both the PDP-11, and VAX-11 made by
  30.                  Digital Equipment Corporation have automatic sign extention of
  31. char.
  32.                  This means that the range of char is from -128 through to +127
  33.                  on these machines. Consult your hardware manual, there may be
  34.                  other exceptions to the trend towards unsigned char as the
  35. default.
  36.  
  37.                  This test program should clear things up for you.
  38.  
  39. /* ----------------------------------------- */
  40.  
  41. #ident "@(#) - Test char signed / unsigned.";
  42.  
  43. #include <stdio.h>
  44.  
  45. main()
  46. {
  47.         char a;
  48.         unsigned char b;
  49.  
  50.         a = b = 128;
  51.         a >>= 1;
  52.         b >>= 1;
  53.   printf ( "\nYour computer has %ssigned char.\n\n", a == b ? "un" : "" );
  54.         }
  55.  
  56. /* ----------------------------------------- */
  57.  
  58.      Here ( Surprise! Surprise! ) is its output on a machine which has
  59.                  unsigned chars.
  60.  
  61. Your computer has unsigned char.
  62.  
  63.     Cut this program out of the news file. Compile and execute it on
  64.                 your computer in order to find out if you have signed or
  65. unsigned char.
  66.  
  67.   b) The Integers.
  68.  
  69.      As you might imagine this is the storage type in which to store whole
  70.      numbers. There are two sizes of integer which are known as short and long.
  71.      The actual number of bits used in both of these types is Implementation
  72.      Dependent. This is the way the jargonauts say that it varies from computer
  73.      to computer. Almost all machines with a word size larger than sixteen bits
  74.                  have the the long int fitting exactly into a machine word and
  75. a short int
  76.      represented by the contents of half a word. It's done this way because
  77.                  most machines have instructions which will perform arithmetic
  78. efficiently
  79.                  on both the complete machine word as well as the half-word.
  80. For the
  81.                  sixteen bit machines, the long integer is two machine words
  82. long,
  83.                  and the short integer is one.
  84.  
  85.   short int smaller_number;
  86.   long int big_number;
  87.  
  88.      Either of the words short or long may be omitted as a default is
  89.                  provided by the compiler. Check your compiler's documentation
  90. to see
  91.                  which default you have been given. Also you should be aware
  92. that some
  93.                  compilers allow the you to arrange for the integers declared
  94. with just
  95.                  the word "int" to be either short or long. The range for a
  96. short int on
  97.                  a small computer is -32768 through to +32767, and for a long
  98. int
  99.                  -4294967296 through to +4294967295.
  100.  
  101.   c) The Real Numbers.
  102.  
  103.      Sometimes known as floating point numbers this number representation
  104.      allows us to store values such as 3.141593, or -56743.098. So, using
  105.      possible examples from a ship design program you declare floats and
  106.      doubles like this:
  107.  
  108.   float length_of_water_line;     /* in meters */
  109.   double displacement;            /* in grammes */
  110.  
  111.      In the same way that the integer type offers two sizes so does the
  112.      floating point representation. They are called float and double. Taking
  113.      the values from the file /usr/include/values.h the ranges which can be
  114.      represented by float and double are:
  115.  
  116.   MAXFLOAT      3.40282346638528860e+38
  117.   MINFLOAT      1.40129846432481707e-45
  118.   MAXDOUBLE     1.79769313486231470e+308
  119.   MINDOUBLE     4.94065645841246544e-324
  120.  
  121.      However you should note that for practical purposes the maximum
  122.                  number of significant digits that can be represented by a
  123. float
  124.                  is approximately six and that by a double is twelve. Also you
  125. should
  126.                  be aware that the above numbers are as defined by the IEEE
  127. floating
  128.                  point standard and that some older machines and compilers do
  129. not
  130.                  conform. All small machines bought retail will conform. If you
  131. are
  132.                  in doubt I suggest that refer to your machine's documentation
  133. for
  134.                  the whole and exact story!
  135.  
  136.  
  137.   d) Signed and unsigned prefixes.
  138.  
  139.      For both the character and integer types the declaration can be
  140.                  preceded by the word "unsigned". This shifts the range so that
  141. 0
  142.                  is the minimum, and the maximum is twice that of the signed
  143. data
  144.                  type in question. It's useful if you know that it is
  145. impossible
  146.                  for the number to go negative. Also if the word in memory is
  147. going
  148.                  to be used as a bit pattern or a mask and not a number the use
  149. of
  150.                  unsigned is strongly urged. If it is possible for the sign bit
  151. in
  152.                  the bit pattern to be set and the program calls for the bit
  153. pattern
  154.                  to be shifted to the right, then you should be aware that the
  155. sign
  156.                  bit will be extended if the variable is not declared unsigned.
  157.                  The default for the "int" types is always "signed", and, as
  158. discussed
  159.                  above that of the "char" is machine dependent.
  160.  
  161.   This completes the discussion on the allocation of data types, except to
  162.   say that we can, of course, allocate arrays of the simple types simply by
  163.   adding a pair of square brackets enclosing a number which is the size of
  164.   the array after the variable's name:
  165.  
  166.   char client_surname[31];
  167.  
  168.   This declaration reserves storage for a string of 30 characters plus the
  169.   NULL character of value zero which terminates the string.
  170.  
  171.   Structures.
  172.  
  173.          Data elements which are logically connected, for example - to use the
  174.          example alluded to above - the dimensions and other details about a
  175. sea
  176.          going ship, can be collected together as a single data unit called a
  177.          struct. One possible way of laying out the struct in the source code
  178. is:
  179.  
  180. struct ship          /* The word "ship" is known as the structure's "tag". */
  181. {
  182.   char name[30];
  183.   double displacement;                           /* in grammes */
  184.   float length_of_water_line;                    /* in meters */
  185.   unsigned short int number_of_passengers;
  186.   unsigned short int number_of_crew;
  187.   };
  188.  
  189.      Note very well that the above fragment of program text does NOT
  190.                  allocate any storage, it merely provides a named template to
  191. the
  192.                  compiler so that it knows how much storage is needed for the
  193.                  structure. The actual allocation of memory is done either like
  194. this:
  195.  
  196. struct ship cunarder;
  197.  
  198.                  Or by putting the name of the struct variable between the "}"
  199. and
  200.                  the ";" on the last line of the definition. Personally I don't
  201.                  use this method as I find that the letters of the name tend to
  202. get
  203.                  "lost" in the - shall we say - amorphous mass of characters
  204. which
  205.                  make up the definition itself.
  206.  
  207.      The individual members of the struct can have values assigned to
  208.                  them in this fashion:
  209.  
  210.   cunarder.displacement = 97500000000.0;
  211.   cunarder.length_of_water_line = 750.0
  212.   cunarder.number_of_passengers = 3575;
  213.   cunarder.number_of_crew = 4592;
  214.  
  215.      These are a couple of files called demo1.c & demo1a.c which contain
  216.                  small 'C' programs for you to compile. So, please cut them out
  217. of the
  218.                  news posting file and do so.
  219.  
  220.  
  221. ----------------------------------------------------------------------
  222. #ident demo1.c  /* If your compiler complains about this line, chop it out */
  223. #include <stdio.h>
  224.  
  225. struct ship
  226. {
  227.   char name[31];
  228.   double displacement;                              /* in grammes */
  229.   float length_of_water_line;                       /* in meters */
  230.   unsigned short int number_of_passengers;
  231.   unsigned short int number_of_crew;
  232.   };
  233.  
  234. char *format = "\
  235. Name of Vessel: %-30s\n\
  236.   Displacement: %13.3f\n\
  237.     Water Line: %5.1f\n\
  238.     Passengers: %4d\n\
  239.           Crew: %4d\n\n";
  240.  
  241. main()
  242. {
  243.   struct ship cunarder;
  244.  
  245.   cunarder.name = "Queen Mary";                  /* This is the bad line. */
  246.   cunarder.displacement = 97500000000.0;
  247.   cunarder.length_of_water_line = 750.0
  248.   cunarder.number_of_passengers = 3575;
  249.   cunarder.number_of_crew = 4592;
  250.  
  251.   printf ( format,
  252.            cunarder.name,
  253.                  cunarder.displacement,
  254.            cunarder.length_of_water_line,
  255.            cunarder.number_of_passengers,
  256.            cunarder.number_of_crew
  257.            );
  258.   }
  259.  
  260. ----------------------------------------------------------------------
  261.  
  262.                  Why is the compiler complaining at line 21?
  263.      Well C is a small language and doesn't have the ability to allocate
  264.      strings to variables within the program text at run-time. This
  265.                  program shows the the correct way to copy the string "Queen
  266. Mary",
  267.                  using a library routine, into the structure.
  268.  
  269.  
  270. ----------------------------------------------------------------------
  271. #ident demo1a.c  /* If your compiler complains about this line, chop it out */
  272. #include <stdio.h>
  273.  
  274. /*
  275. ** This is the template which is used by the compiler so that
  276. ** it 'knows' how to put your data into a named area of memory.
  277. */
  278.  
  279. struct ship
  280. {
  281.   char name[31];
  282.   double displacement;                              /* in grammes */
  283.   float length_of_water_line;                       /* in meters */
  284.   unsigned short int number_of_passengers;
  285.   unsigned short int number_of_crew;
  286.   };
  287.  
  288. /*
  289. ** This character string tells the printf() function how it is to output
  290. ** the data onto the screen. Note the use of the \ character at the end
  291. ** of each line. It is the 'continue the string on the next line' flag
  292. ** or escape character. It MUST be the last character on the line.
  293. ** This technique allows you to produce nicely formatted reports with all the
  294. ** ':' characters under each other, without having to count the characters
  295. ** in each character field.
  296. */
  297.  
  298. char *format = "\n\
  299. Name of Vessel: %-30s\n\
  300.   Displacement: %13.1f grammes\n\
  301.     Water Line: %5.1f metres\n\
  302.     Passengers: %4d\n\
  303.           Crew: %4d\n\n";
  304.  
  305. main()
  306. {
  307.   struct ship cunarder;
  308.  
  309.   strcpy ( cunarder.name, "Queen Mary" );           /* The corrected line */
  310.   cunarder.displacement = 97500000000.0;
  311.   cunarder.length_of_water_line = 750.0;
  312.   cunarder.number_of_passengers = 3575;
  313.   cunarder.number_of_crew = 4592;
  314.  
  315.   printf ( format,
  316.            cunarder.name,
  317.                                  cunarder.displacement,
  318.            cunarder.length_of_water_line,
  319.            cunarder.number_of_passengers,
  320.            cunarder.number_of_crew
  321.                                  );
  322.   }
  323.  
  324. ----------------------------------------------------------------------
  325.  
  326.      I'd like to suggest that you compile the program demo1a.c and execute it.
  327.  
  328. $ cc demo1a.c
  329. $ a.out
  330.  
  331. Name of Vessel: Queen Mary
  332.   Displacement: 97500000000.0 grammes
  333.     Water Line: 750.0 metres
  334.     Passengers: 3575
  335.           Crew: 4592
  336.  
  337.      Which is the output of our totally trivial program to demonstrate
  338.      the use of structures.
  339.  
  340.   Tip:
  341.  
  342.      To avoid muddles in your mind and gross confusion in other minds
  343.      remember that you should ALWAYS declare a variable using a name which is
  344.      long enough to make it ABSOLUTELY obvious what you are talking about.
  345.  
  346.         Storage Classes.
  347.  
  348.         The little dissertation above about the storage of variables was
  349.         concerned with the sizes of the various types of data. There is
  350.         just the little matter of the position in memory of the variables'
  351.         storage.
  352.  
  353.         'C' has been designed to maximise the the use of memory by allowing you
  354.         to re-cycle it automatically when you have finished with it.
  355.         A variable defined in this way is known as an 'automatic' one. Although
  356.         this is the default behaviour you are allowed to put the word 'auto' in
  357.         front of the word which states the variable's type in the definition.
  358.         It is quite a good idea to use this so that you can remind yourself
  359.         that this variable is, in fact, an automatic one. There are three other
  360.         storage allocation methods, 'static' and 'register', and 'const'.
  361.         The 'static' method places the variable in main storage for the whole
  362.         of the time your program is executing. In other words it kills the
  363.         're-cycling' mechanism. This also means that the value stored there
  364.         is also available all the time. The 'register' method is very machine
  365.         and implementation dependent, and also perhaps somewhat archaic in
  366.         that the optimiser phase of the compilation process does it all for
  367.         you. For the sake of completeness I'll explain. Computers have a small
  368.         number of places to store numbers which can be accessed very quickly.
  369.         These places are called the registers of the Central Processing Unit.
  370.         The 'register' variables are placed in these machine registers instead
  371. of
  372.         stack or main memory. For program segments which are tiny loops the
  373. speed
  374.         at which your program executes can be enhanced quite remarkably.
  375.         The optimiser compilation phase places as many of your variables into
  376.         registers as it can. However no machine can decide which of the
  377. variables
  378.         should be placed in a register, and which may be left in memory, so if
  379.         your program has many variables and two or three should be register
  380. ones
  381.         then you should specify which ones the compiler.
  382.  
  383.         All this is dealt with at much greater detail later in the course.
  384.  
  385.         Pointers.
  386.  
  387.         'C' has the very useful ability to set up pointers. These are memory
  388.         cells which contain the address of a data element. The variable name is
  389.         preceeded by a '*' character. So, to reserve an element of type char
  390. and
  391.   a pointer to an element of type char, one would say.
  392.  
  393. char c;
  394. char *ch_p;
  395.  
  396.   I always put the suffix '_p' on the end of all pointer variables
  397.         simply so that I can easily remember that they are in fact pointers.
  398.  
  399.         There is also the companion unary operator '&' which yields the
  400.         address of the variable. So to initialize our pointer ch_p to point
  401.         at the char c, we have to say.
  402.  
  403.   ch_p = &c;
  404.  
  405.   Note very well that the process of indirection can procede to any
  406.         desired depth, However it is difficult for the puny brain of a normal
  407.         human to conceptualize and remember more that three levels! So be
  408. careful
  409.         to provide a very detailed and precise commentry in your program if
  410.         you put more than two or three stars.
  411.  
  412.  
  413.   Getting data in and out of your programs.
  414.  
  415.         As mentioned before 'C' is a small language and there are no intrinsic
  416.         operators to either convert between binary numbers and ascii
  417.         characters or to transfer information to and fro between the
  418.         computer's memory and the peripheral equipment, such as terminals or
  419.         disk stores.
  420.  
  421.         This is all done using the i/o functions declared in the file stdio.h
  422.         which you should have examined earlier. Right now we are going to look
  423.         at the functions "printf" and "scanf". These two functions together
  424.         with their derivatives, perform i/o to the stdin and stdout files,
  425.         i/o to nominated files, and internal format conversions. This means
  426.         the conversion of data from ascii character strings to binary numbers
  427.         and vice versa completely within the computer's memory. It's more
  428.         efficient to set up a line of print inside memory and then to send the
  429.         whole line to the printer, terminal, or whatever, instead of
  430.         "squirting" the letters out in dribs and drabs!
  431.  
  432.         Study of them will give you understanding of a very convenient way to
  433.         talk to the "outside world".
  434.  
  435.         So, remembering that one of the most important things you learn in
  436.         computing is "where to look it up", lets do just that.
  437.         If you are using a computer which has the unix operating system,
  438.         find your copy of the "Programmer Reference Manual" and turn to the
  439.         page printf(3S), alternatively, if your computer is using some other
  440.         operating system, then refer to the section of the documentation which
  441.         describes the functions in the program library.
  442.  
  443.         You will see something like this:-
  444.  
  445.         NAME
  446.                                 printf, fprintf, sprintf - print formatted
  447. output.
  448.  
  449.         SYNOPSIS
  450.                                 #include <stdio.h>
  451.  
  452.                                 int printf ( format [ , arg ] ... )
  453.                                 char *format;
  454.  
  455.                                 int fprintf ( stream, format [ , arg ] ... )
  456.                                 FILE *stream;
  457.                                 char *format;
  458.  
  459.                                 int sprintf ( s, format [ , arg ] ... )
  460.                                 char *s, *format;
  461.  
  462.         DESCRIPTION
  463.  
  464.                                 etc... etc...
  465.  
  466.         The NAME section above is obvious isn't it?
  467.  
  468.         The SYNOPSIS starts with the line #include <stdio.h>. This tells
  469.         you that you MUST put this #include line in your 'C' source code
  470.         before you mention any of the routines. The rest of the paragraph
  471.         tells you how to call the routines. The " [ , arg ] ... " heiroglyph
  472.         in effect says that you may have as many arguments here as you wish,
  473.         but that you need not have any at all.
  474.  
  475.   The DESCRIPTION explains how to use the functions.
  476.  
  477.         Important Point to Note:
  478.  
  479.         Far too many people ( including the author ) ignore the fact that
  480.         the printf family of functions return a useful number which can be
  481.         used to check that the conversion has been done correctly, and that
  482.         the i/o operation has been completed without error.
  483.  
  484.   Refer to the format string in the demonstration program above for
  485.         an example of a fairly sophisticated formatting string.
  486.  
  487.   In order to fix the concepts of printf in you mind, you
  488.         might care to write a program which prints some text in three ways:
  489.  
  490. a) Justified to the left of the page. ( Normal printing. )
  491. b) Justified to the right of the page.
  492. c) Centred exactly in the middle of the page.
  493.  
  494.         Suggestions and Hint.
  495.  
  496.         Set up a data area of text using the first verse of "Quangle" as data.
  497.         Here is the program fragment for the data:-
  498.  
  499. /* ----------------------------------------- */
  500.  
  501. char *verse[] =
  502. {
  503.   "On top of the Crumpetty Tree",
  504.   "The Quangle Wangle sat,",
  505.   "But his face you could not see,",
  506.   "On account of his Beaver Hat.",
  507.   "For his Hat was a hundred and two feet wide.",
  508.   "With ribbons and bibbons on every side,",
  509.   "And bells, and buttons, and loops, and lace,",
  510.   "So that nobody ever could see the face",
  511.   "Of the Quangle Wangle Quee.",
  512.   NULL
  513.   };
  514.  
  515. /* ----------------------------------------- */
  516.  
  517.   Cut it out of the news file and use it in a 'C' program file called
  518.         verse.c
  519.  
  520.         Now write a main() function which uses printf alone for (a) & (b)
  521.         You can use both printf() and sprintf() in order to create
  522.         a solution for (c) which makes a good use of the capabilities
  523.         of the printf family. The big hint is that the string controlling
  524.         the format of the printing can change dynamically as program execution
  525.         proceeds. A possible solution is presented in the file verse.c which is
  526.         appended here. I'd like to suggest that you have a good try at making
  527.         a program of you own before looking at my solution.
  528.         ( One of many I'm sure )
  529.  
  530. /* ----------------------------------------- */
  531.  
  532. #include <stdio.h>
  533.  
  534. char *verse[] =
  535. {
  536.   "On top of the Crumpetty Tree",
  537.   "The Quangle Wangle sat,",
  538.   "But his face you could not see,",
  539.   "On account of his Beaver Hat.",
  540.   "For his Hat was a hundred and two feet wide.",
  541.   "With ribbons and bibbons on every side,",
  542.   "And bells, and buttons, and loops, and lace,",
  543.   "So that nobody ever could see the face",
  544.   "Of the Quangle Wangle Quee.",
  545.   NULL
  546.   };
  547.  
  548. main()
  549. {
  550.         char **ch_pp;
  551.  
  552.         /*
  553.         ** This will print the data left justified.
  554.         */
  555.  
  556.         for ( ch_pp = verse; *ch_pp; ch_pp++ ) printf ( "%s\n", *ch_pp );
  557.         printf( "\n" );
  558.  
  559.         /*
  560.         ** This will print the data right justified.
  561.         **
  562.         **  ( As this will print a character in column 80 of
  563.         **    the terminal you should make sure any terminal setting
  564.         **    which automatically inserts a new line is turned off. )
  565.         */
  566.  
  567.         for ( ch_pp = verse; *ch_pp; ch_pp++ ) printf ( "%79s\n", *ch_pp );
  568.         printf( "\n" );
  569.  
  570.         /*
  571.         ** This will centre the data.
  572.         */
  573.  
  574.         for ( ch_pp = verse; *ch_pp; ch_pp++ )
  575.         {
  576.                 int length;
  577.                 char format[10];
  578.  
  579.                 length = 40 + strlen ( *ch_pp ) / 2;      /* Calculate the
  580. field length  */
  581.                 sprintf ( format, "%%%ds\n", length );    /* Make a format
  582. string.       */
  583.                 printf ( format, *ch_pp );                /* Print line of
  584. verse, using  */
  585.                 }                                         /* generated format
  586. string     */
  587.         printf( "\n" );
  588.         }
  589.  
  590. /* ----------------------------------------- */
  591.  
  592.   If you cheated and looked at my example before even attempting
  593.         to have a go, you must pay the penalty and explain fully why
  594.         there are THREE "%" signs in the line which starts with a call
  595.         to the sprintf function. It's a good idea to do this anyway!
  596.  
  597.  
  598.   So much for printf(). Lets examine it's functional opposite - scanf(),
  599.  
  600.         Scanf is the family of functions used to input from the outside world
  601.         and to perform internal format conversions from character strings to
  602.         binary numbers. Refer to the entry scanf(3S) in the Programmer
  603.         Reference Manual. ( Just a few pages further on from printf. )
  604.  
  605.   The "Important Point to Note" for the scanf family is that the
  606.         arguments to the function are all POINTERS. The format string has to
  607.         be passed in to the function using a pointer, simply because this
  608.         is the way 'C' passes strings, and as the function itself has to store
  609.         its results into your program it ( the scanf function ) has to "know"
  610.         where you want it to put them.
  611.  
  612. Copyright notice:-
  613.  
  614. (c) 1993 Christopher Sawtell.
  615.  
  616. I assert the right to be known as the author, and owner of the
  617. intellectual property rights of all the files in this material,
  618. except for the quoted examples which have their individual
  619. copyright notices. Permission is granted for onward copying,
  620. but not modification, of this course and its use for personal
  621. study only, provided all the copyright notices are left in the
  622. text and are printed in full on any subsequent paper reproduction.
  623.  
  624. --
  625.  +----------------------------------------------------------------------+
  626.  | NAME   Christopher Sawtell                                           |
  627.  | SMAIL  215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
  628.  | EMAIL  chris@gerty.equinox.gen.nz                                    |
  629.  | PHONE  +64-3-389-3200   ( gmt +13 - your discretion is requested )   |
  630.  +----------------------------------------------------------------------+
  631.